using Game.Config;
using Pathfinding;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Rendering;

public class FSM : MonoBehaviour
{
    // Start is called before the first frame update

    public bool Ai;

    //ExcelID
    public int id;

    [HideInInspector]
    public PlayerState currentState;
    [HideInInspector]
    public UnitEntity unitEntity;

    Dictionary<int,PlayerState>stateData = new Dictionary<int,PlayerState>();

    [HideInInspector]
    public Transform _transform;
    [HideInInspector]
    public GameObject _gameObject;

    [HideInInspector]
    public Animator animator;
    [HideInInspector]
    public CharacterController characterController;

    [HideInInspector]
    public int instance_id;

    [HideInInspector]
    public Seeker seeker;


    public UnitAttEntity att_base; //总属性

    public UnitAttEntity att_crn;//当前属性==>生命值

    public int global_state;//全局的状态 0战斗 1和平


    private void Awake()
    {
        _transform = transform;
        _gameObject = gameObject;

        unitEntity = UnitData.Get(id);
        att_base = AttHelper.Instance.Create(unitEntity.att_id);
        att_crn = AttHelper.Instance.Create(att_base);
        animator = _transform.GetChild(0).GetComponent<Animator>();
        characterController = GetComponent<CharacterController>();
        instance_id = _gameObject.GetInstanceID();


        ServiceInit();
        StateInit();
        InitSeek();

        if (Ai == false)
        {
            UnitManager.Instance.Player = this;
        }
        ToNext(1001);//idle
    }

    void InitSeek()
    {
        seeker = _gameObject.GetComponent<Seeker>();
        if (seeker == null)
        {
            seeker = _gameObject.AddComponent<Seeker>();
        }
        seeker.startEndModifier = new StartEndModifier();
        seeker.startEndModifier.exactStartPoint = StartEndModifier.Exactness.Original;
        seeker.startEndModifier.exactEndPoint = StartEndModifier.Exactness.Original;
        seeker.drawGizmos = true;

        _gameObject.AddComponent<SimpleSmoothModifier>(); //解决路线曲折曲折的问题 平滑路线 

    }

    // Update is called once per frame
    void Update()
    {
        if (currentState != null)
        {
            if (ServicesOnUpdate() == true)
            {
                DoStateEvent(currentState.id, StateEventType.update);

            }

            ToGround(); 
        }
        
    }
    
    public void AnimationOnPlayEnd()
    {
        int id = currentState.id;
        DoStateEvent(currentState.id, StateEventType.animtionEnd);
        //对应 on_anm_end 字段 -1不需要做处理  0表示循环动作 其他表示为切成其他状态
        ServicesOnAnimationEnd(); //回调给除了角色以外的处理 很可能是为了给怪物监听人物的攻击后摇 喝药后摇

        if (currentState.id != id) //表示当前状态 不一样
        {
            return;
        }


        switch (currentState.excel_Config.on_anm_end)
        {
            case -1:
                break;
            case 0:
                ServicesOnRestart();
                return;
            default:
                ToNext(currentState.excel_Config.on_anm_end);
                break;

        }

    }
    public bool ToNext(int next)
    {
        if (stateData.ContainsKey(next))
        {
            if (currentState != null)
            {
                Debug.Log($"{this.gameObject.name}:切换状态:{stateData[next].Info()} 当前是:{currentState.Info()}");   
                //状态绑定的退出事件
                DoStateEvent(currentState.id, StateEventType.end);
                ServicesOnEnd();
            }
            else
            {
                Debug.Log($"{this.gameObject.name}:切换状态:{stateData[next].Info()}");
            }

            currentState = stateData[next];
            currentState.SetBeginTime();
            ServicesOnBegin();
            DoStateEvent(currentState.id, StateEventType.begin);
            //当前状态的进入事件
            return true;
        }
        return false;
    }

    //存储每个状态 id <不同类型事件 ，不同类型事件

    public Dictionary<int, Dictionary<StateEventType, List<Action>>> actions = new Dictionary<int, Dictionary<StateEventType, List<Action>>>();

    /// <summary>
    /// 添加事件 往给定id的状态中 添加 该状态的 StateEventType 也就是某个时候 一个或者多个给定事件
    /// </summary>
    /// <param name="id">状态id</param>
    /// <param name="t">状态进入的时刻</param>
    /// <param name="action">事件</param>
    public void AddListener(int id,StateEventType t,Action action)
    {
        if (!actions.ContainsKey(id))
        {
             actions[id] = new Dictionary<StateEventType, List<Action>>();

        }
        
        if(!actions[id].ContainsKey(t)) 
        {
            //actions[id] = new Dictionary<StateEventType, List<Action>>();
            List<Action> list = new List<Action>();
            actions[id][t] = list;
            actions[id][t].Add(action);
        }
        else
        {
            actions[id][t].Add(action);

        }
    }


    /// <summary>
    /// 调用 某个状态某个时刻的所有事件
    /// </summary>
    /// <param name="id"></param>
    /// <param name="t"></param>
    public void DoStateEvent(int id,StateEventType t)
    {
        if(actions.TryGetValue(id,out var v))
        {
            if(v.TryGetValue(t,out var list))
            {
                foreach(var item in list)
                {
                    item?.Invoke();
                }              
            }
            
        }
    }

    StateScripttableObject anmConfig;
    public void StateInit()
    {
        //取配置
        anmConfig = Resources.Load<StateScripttableObject>($"Config/StateConfig/{id}");
        Dictionary<int,StateEntity> state_config = new Dictionary<int, StateEntity> ();
        foreach(var item in anmConfig.states)
        {
            state_config[item.id] = item;
        }

        //取动画片段长度
        var clips = animator.runtimeAnimatorController.animationClips;
        Dictionary<string,float> clipLength = new Dictionary<string, float> ();
        foreach(var cl in clips)
        {
            clipLength[cl.name] = cl.length;
        }

        if (PlayerStateData.all != null)
        {
            foreach(var item in PlayerStateData.all)
            {
                PlayerState p = new PlayerState();
                p.excel_Config = item.Value;
                p.id = item.Key;
                p.stateEntity = state_config[p.id];

                if(clipLength.TryGetValue(item.Value.anm_name,out var length))
                {
                    p.clipLength = length;
                }
                stateData[item.Key] = p;
            }
        }

        stateData[1005].skill = SkillData.Get(unitEntity.ntk1);
        stateData[1006].skill = SkillData.Get(unitEntity.ntk1);
        stateData[1007].skill = SkillData.Get(unitEntity.ntk1);
        stateData[1008].skill = SkillData.Get(unitEntity.ntk1);

        stateData[1009].skill = SkillData.Get(unitEntity.skill1);
        stateData[1010].skill = SkillData.Get(unitEntity.skill2);
        stateData[1011].skill = SkillData.Get(unitEntity.skill3);
        stateData[1012].skill = SkillData.Get(unitEntity.skill4);
    
        
        if(Ai == false)
        {
            //主角的
            foreach(var item in stateData)
            {
                if(item.Value.excel_Config.on_move != null)
                {
                    AddListener(item.Key, StateEventType.update, OnMove); //播移动动画 
                }

                if(item.Value.excel_Config.do_move == 1)
                {
                    AddListener(item.Key, StateEventType.update, PlayerMove);  //做移动逻辑
                }

                if (item.Value.excel_Config.on_stop != 0)
                {
                    AddListener(item.Key, StateEventType.update, OnStop);
                }

                if (item.Value.excel_Config.on_jump != null)
                {
                    AddListener(item.Key, StateEventType.update, OnJump);
                }

                if (item.Value.excel_Config.on_jump_end != 0)  //跳跃在空中 做着地检测
                {
                    AddListener(item.Key, StateEventType.update, OnJumpUpdate);
                }

                if(item.Value.excel_Config.add_f_move > 0)
                {
                    AddListener(item.Key, StateEventType.update, AddForwardMove);
                }

                if (item.Value.excel_Config.on_atk !=null) // idle->攻击 空中攻击
                {
                    AddListener(item.Key, StateEventType.update, OnAtk);
                }

                if (item.Value.excel_Config.on_skill1 != null)
                {
                    AddListener(item.Key, StateEventType.update, OnSkill1);
                }

                if (item.Value.excel_Config.on_defense != null)
                {
                    AddListener(item.Key, StateEventType.update, OnDefense);
                }

                if (item.Value.excel_Config.on_defense_quit != 0)
                {
                    AddListener(item.Key, StateEventType.update, OnDefenseQuit);
                }

                if(item.Value.stateEntity.ignor_collision == true)
                {
                    AddListener(item.Key, StateEventType.begin, DisableCollider);
                    AddListener(item.Key, StateEventType.end, EnableCollider);
                }

                if (item.Value.skill != null)
                {
                    AddListener(item.Key, StateEventType.begin, OnSkill1Begin);
                    AddListener(item.Key, StateEventType.begin, SetSkillCD);
                }

            }
        }
        else
        {
            //要注册的事件

            foreach(var item in stateData)
            {
                //进入状态的多久 会触发攻击
                if(item.Value.excel_Config.active_attack > 0)
                {
                   AddListener(item.Key, StateEventType.update, AutoTriggerAtk_AI);
                }

                if (item.Value.excel_Config.trigger_pacing > 0)
                {
                    AddListener(item.Key, StateEventType.animtionEnd, TriggerPacing_AI);
                }

                if (item.Value.excel_Config.tag == 4)
                {
                    AddListener(item.Key, StateEventType.update, OnPacing_AIUpdate);
                }

                if(item.Value.excel_Config.trigger_patrol > 0)
                {
                    AddListener(item.Key, StateEventType.update, TriggerPatrol);
                }
            }
            GameEvent.OnPlayerSkill += OnPlayerSkill1;
            AddListener(1014, StateEventType.animtionEnd, OnDashEnd);
            AddListener(1042, StateEventType.update, OnMoveToPoint);
            AddListener(1042, StateEventType.end, NavStop);
            AddListener(1013, StateEventType.update, AI_Defending);
            AddListener(10131, StateEventType.update, AI_Defending);
            AddListener(1043, StateEventType.update, OnPatrolUpdate);
            AddListener(1043, StateEventType.begin, ChangeMoveSpeed);
            AddListener(1043, StateEventType.end, ResetMoveSpeed);

            AddListener(1017, StateEventType.update, OnBashUpdate);
            AddListener(1017, StateEventType.end,OnBashEnd);

            AddListener(1018, StateEventType.update, OnBashUpdate);
            AddListener(1018, StateEventType.end, OnBashEnd);
        }
    }

    private void SetSkillCD()
    {
        if (currentState.id == 1009)
        {
            MainViewController.Instance.SetSKillCD(0, currentState.skill.cd);
        }
        else if (currentState.id == 1010)
        {
            MainViewController.Instance.SetSKillCD(1, currentState.skill.cd);
        }
        else if (currentState.id == 1011)
        {
            MainViewController.Instance.SetSKillCD(2, currentState.skill.cd);
        }
        else if(currentState.id == 1012)
        {
            MainViewController.Instance.SetSKillCD(3, currentState.skill.cd);
        }
    }

    private void OnEnable()
    {
        if (Ai)
        {
            if(unitEntity.type == 3)
            {
                //MainViewController.Instance.EnableBossUiHp(true,unitEntity.info);
            }
        }
    }

    private void ResetMoveSpeed()
    {
        moveSpeed = 3f;
        navGraphService.Stop(); //如果出现 走着走着突然被拉回去 就要考虑是不是 因为物理位移配置 和 a*导航冲突
    }

    private void ChangeMoveSpeed()
    {
        moveSpeed = 2f;
    }

    /// <summary>
    /// 触发巡逻
    /// </summary>
    private void TriggerPatrol()
    {
        if(atk_target ==null ||  GetDst() > 10)
        {
            if (GameTime.time - currentState.begin >= currentState.excel_Config.trigger_patrol)
            {
                //进入巡逻

                //自身周边3-6m的位置

                var r = IntEx.Range(3, 6);
                var angle = IntEx.Range(0, 359);
                var position = _transform.GetOffsetPosition(r, angle);
                _transform.LookTarget(position);    
                navGraphService.Move(position, ToPatrol);

                
            }
        }

    }



    /// <summary>
    /// 1、巡逻到目的地后(被地形卡住 或者一堆问题 导致超时) 停止 3-5s 
    /// </summary>
   public void OnPatrolUpdate()
    {
        if (isOverTime(5f) || navGraphService.IsEnd())
        {
            ToNext(1001);
        }
    }

    private bool isOverTime(float time)
    {
        return GameTime.time - currentState.begin >= time;
    }

    //生成巡逻路线
    public void ToPatrol()
    {
        ToNext(1043);
    }


    
    private void AI_Defending()
    {
        LookAtkTarget();

        ///超过2.5f 后 回到待机
        
        if (isOverTime(2.5f))
        {
            ToNext(10132);
        }
    }

    private void OnPacing_AIUpdate()
    {
        if (isOverTime(5f))
        {
            ToNext(1001);
            return;
        }

        if (atk_target != null)
        {
            //如何解决 几个攻击状态冲突
            LookAtkTarget();
            if (GetDst() <= 3)
            {
                AIAtk();
                return;
            }
        }

    }
    private void LookAtkTarget()
    {
        if (atk_target != null)
        {
            _transform.LookTarget(atk_target._transform);
        }
    }

    private void TriggerPacing_AI()
    {
        if (atk_target == null)
        {
            var dst = GetDst();
            if (dst > 10)
            {
                return;
            }
            else
            {
                atk_target = UnitManager.Instance.Player;
            }

        }

        if (IsDead())
            return;
        if (unitEntity.pacing_probability > 0)
        {

            if (unitEntity.pacing_probability.isInRange())
            {
                if (atk_target == null)
                {
                    var dst = Vector3.Distance(_transform.position, UnitManager.Instance.Player._transform.position);
                    if (dst < 10)
                    {
                        atk_target = UnitManager.Instance.Player;
                    }
                    else
                    {
                        return;
                    }
                }

                if (currentState.excel_Config.tag == 4)
                {
                    if (GameTime.time - currentState.begin >= IntEx.Range(3, 6))
                    {
                        var next = IntEx.Range(1038, 1039);
                        _transform.LookTarget(atk_target._transform);
                        ToNext(next);
                    }
                }
                else
                {
                    var next = IntEx.Range(1038, 1039);
                    _transform.LookTarget(atk_target._transform);
                    ToNext(next);
                }
            }
        }
    }

    private void AutoTriggerAtk_AI()
    {

        if (GameTime.time - currentState.begin >= currentState.excel_Config.active_attack)
        {
            AIAtk();
        }
    }

    float _OnMoveToPoint_CheckTime;
    private void OnMoveToPoint()
    {
        if (GameTime.time - _OnMoveToPoint_CheckTime > 0.1)
        {
            _OnMoveToPoint_CheckTime = GameTime.time;

            if (next_atk != 0 && atk_target != null)
            {
                var dst = GetDst();
                if (dst <= stateData[next_atk].skill.atk_distance)
                {
                    navGraphService.Stop();
                    this._transform.LookTarget(atk_target._transform);
                    ToNext(next_atk);
                    next_atk = 0;
                }
                else
                {
                    //寻路到终点了  或者移动超时5f
                    if (navGraphService.IsEnd() || GameTime.time - currentState.begin >= 5f)
                    {
                        navGraphService.Stop();
                        AIAtk();
                        next_atk = 0;
                    }
                }
            }
            else if (next_atk ==0)
            {
                //ToNext(1001);
            }
        }
    }

    public void RemoveListener()
    {
        GameEvent.OnPlayerSkill -= OnPlayerSkill1;
    }

    private void OnPlayerSkill1(FSM atk, SkillEntity entity)
    {
        if (att_base.hp <= 0) return;
        //这里要看 哪一些单位 对主角的这个 状态/行为 感兴趣

        //例如

        //1、这里接入视野机制作条件 怪物朝向 巴拉巴拉
        //2、接入距离作条件
        //3、接入当前npc /怪物 的状态 可切换的状态 作条件

        if (unitEntity.atk_probability.isInRange())
        {
            if (currentState.excel_Config.first_strike > 0)
            {
                TriggerAtk_AI();
                return;
            }
        }

        if (Vector3.Distance(atk._transform.position, this._transform.position) <= 3f)
        {


            if (unitEntity.block_probability.isInRange())
            {
                //这部分可以继续抽出来 因为很多怪都是对主角行为 （攻击、技能） 是感兴趣的 
                //响应这部分状态 也就是AI处理 玩家的出招  怪物/AI 可以进入的状态 有例如
                //1、 闪避/ 2、 攻击/  3、变身 

                //1、例如 某个杨戬会对你的三豆 然后侧身一下 闪避 
                //2、例如 某些熔炉骑士 会对你的喝药 在距离内 然后直接打断  攻击
                //3、例如 某个杨戬会在你 化身的时候打回原型  变身 
                if (currentState.excel_Config.on_defense != null)
                {
                    if (CheckConfig(currentState.excel_Config.on_defense))
                    {
                        _transform.LookTarget(atk._transform.position);
                        var result = ToNext((int)currentState.excel_Config.on_defense[2]);
                        if (result)
                        {
                            return;
                        }
                    }
                }


            }

            if (unitEntity.dodge_probability.isInRange())
            {
                if(currentState.excel_Config.trigger_dodge > 0)
                {
                    if (this._transform.SameForward(atk._transform.forward)>0)return;
                    var f = this._transform.Angle(atk._transform.position);

                    bool result = false;
                    if (f >= 270 && f < 340)   //l_dodge
                    {
                        result = ToNext(1034);
                    } 
                    else if (f >= 340 && f < 360 || f >= 0 && f < 20) //b_dodge
                    {
                        result = ToNext(1033);
                    }
                    else if (f >= 20 && f < 90) //r_dodge
                    {
                        result = ToNext(1035);
                    }
                    if (result)
                    {
                        //闪避功能
                        _transform.LookTarget(atk._transform.position);
                        return;
                    }
                }
            }
        }
    }

    private void TriggerAtk_AI()
    {
        if(animationService.normalizedTime >= currentState.excel_Config.trigger_atk)  //强攻
        {
            AIAtk();
        }

    }

    int next_atk;

    public bool IsDead()
    {
        return att_base.hp <= 0;
    }
    private void AIAtk()
    {
        if (IsDead())
        {
            return;
        }
        next_atk = IntEx.Range(1005, 1009);//1005;//

        //挑选攻击的决策
        //根据对方的技能ID 自己做出对应的技能ID

        if (stateData[next_atk].skill.atk_distance > 0)
        {
            if (atk_target == null)
            {
                atk_target = UnitManager.Instance.Player;
            }
            if (GetDst() >= stateData[next_atk].skill.atk_distance)
            {
                this._transform.LookTarget(atk_target._transform);
                if (IntEx.Range(0, 100) <= 50)
                {
                    //寻路移动过去 
                    if (navGraphService.state == 0)
                    {
                        navGraphService.Move(atk_target._transform.position, MoveToPoint);
                    }
                }
                else
                {
                    ToNext(1014); //突进冲刺 
                }

            }
            else
            {
                this._transform.LookTarget(atk_target._transform);
                if (currentState.excel_Config.on_atk != null)
                    if (CheckConfig(currentState.excel_Config.on_atk))
                        ToNext(next_atk);
            }
        }
    }
    //EnemyHUD enemyHUD;
    internal void UpdateHP_OnHit(int damage)
    {
        //if (AI == false) {
        //    this.att_crn.hp -= 1;
        //}
        //else
        //{
        //    //this.att_crn.hp -= 1;
        //}

        this.att_crn.hp -= damage;

        if (this.att_crn.hp < 0)
        {
            this.att_crn.hp = 0;
        }
        float v = this.att_crn.hp / this.att_base.hp;
        //Debug.LogError($"{this._gameObject.name}:剩余血量:{this.att_crn.hp}");
        if (Ai)
        {
            //更新敌人血条 
            if (unitEntity.type == 3)
            {
                //更新Boss的血条
                MainViewController.Instance.EnableBossUiHp(true,unitEntity.info);
                MainViewController.Instance.UpdateBossHp(v);
            }
            else
            {
                //更新小兵的血条
                //UpdateEnemyHUD();
            }
        }
        else
        {
            //更新主角的血条
            MainViewController.Instance.UpdatePlayerHp(v);
        }

    }
    private void MoveToPoint()
    {
        ToNext(1042);
    }

    public void NavStop()
    {
        navGraphService.Stop();
    }

    public float GetDst()
    {
        return Vector3.Distance(this._transform.position, UnitManager.Instance.Player._transform.position);
    }

    public float GetDst(Transform target)
    {
        return Vector3.Distance(this._transform.position, target.position);
    }

    public void OnDashEnd()
    {
        if(next_atk!=0 && atk_target != null)
        {
            var dst = Vector3.Distance(this._transform.position, atk_target.transform.position);
            if(dst <= stateData[next_atk].skill.atk_distance)
            {
                this.transform.LookTarget(atk_target._transform);
                ToNext(next_atk);
                next_atk = 0;   
            }
            else
            {
                AIAtk();
            }
        }
    }
    private void OnSkill1Begin()
    {
        GameEvent.OnPlayerSkill?.Invoke(this, currentState.skill);
    }

    private void EnableCollider()
    {
        characterController.excludeLayers = 0;
    }

    private void DisableCollider()
    {
        characterController.excludeLayers = GameDefine.Enemy_LayerMask;
    }

    private void OnDefenseQuit()
    {
        if (UInput.GetMouseButtonUp_1())
        {
            ToNext((int)currentState.excel_Config.on_defense_quit);
        }
    }

    private void OnDefense()
    {
        if (UInput.GetMouseButtonDown_1())
        {
            if (CheckConfig(currentState.excel_Config.on_defense))
            {
                ToNext((int)currentState.excel_Config.on_defense[2]);
            }
        }
    }

    private void OnSkill1()
    {
        if (UInput.GetKeyDown_Q())
        {
            if (CheckConfig(currentState.excel_Config.on_skill1))
            {
                ToNext((int)currentState.excel_Config.on_skill1[2]);
            }
        }
    }

    private void OnAtk()
    {
        if (UInput.GetMouseButtonUp_0())
        {
            if (CheckConfig(currentState.excel_Config.on_atk))
            {
                ToNext((int)currentState.excel_Config.on_atk[2]);
            }
        }

    }

    private void AddForwardMove()
    {
        var x = UInput.GetAxis_Horizontal();
        var z = UInput.GetAxis_Vertical();

        //前进跳跃

        if(x!=0 || z > 0)
        {
            if (CheckConfig(currentState.excel_Config.do_rotate))
            {
                var v = new Vector3(x, 0, z > 0 ? z : 0).normalized * currentState.excel_Config.add_f_move;

                //保证一秒内是恒定的
                Move(v, true, true, false, false);
                Rotation(v);
            }
            

        }
    }

    private void OnJump()
    {
        if (UInput.GetKeyDown_Space())
        {
            if(CheckConfig(currentState.excel_Config.on_jump))
            {
                ToNext((int)currentState.excel_Config.on_jump[2]); // 前面两个是前摇
            }
        }
    }

    public void OnJumpUpdate()
    {
        if (Physics.Raycast(_transform.position, -_transform.up, 0.15f, GameDefine.Ground_LayerMask))
        {
            ToNext((int)currentState.excel_Config.on_jump_end); // 前面两个是前摇
        }
    }

    private void OnStop()
    {
        if (UInput.GetAxis_Horizontal() ==0 && UInput.GetAxis_Vertical() ==0)
        {
            ToNext(currentState.excel_Config.on_stop);

        }
    }

    float _targetRotation;

    float _rotationVeloctity;
    float rotationSmoothTime = 0.05f;
    public float moveSpeed = 5f;

    Vector3 inputDirction = new Vector3(); 
    private void PlayerMove()
    {
        var x = UInput.GetAxis_Horizontal();
        var z = UInput.GetAxis_Vertical();


        if (x != 0 || z != 0)
        {
            this.inputDirction.Set(x, 0f, z);
            Rotation(inputDirction);
            Vector3 targetDirection = Quaternion.Euler(0f, _targetRotation, 0f) * Vector3.forward;
            Move(targetDirection.normalized * (moveSpeed *GameDefine.deltaTime), false, false,false);
        }
    }

    /// <summary>
    /// 检查当前动作进度的一个接口，是否处于动作的前摇/后摇阶段 是否能打断掉
    /// </summary>
    /// <param name="config"></param>
    /// <returns></returns>
    public bool CheckConfig(float[] config)
    {
        //检查当前动作进度
        if (config == null) return false;
        return ((animationService.normalizedTime >= 0 && animationService.normalizedTime <= config[0])
            || (animationService.normalizedTime >= config[1] && animationService.normalizedTime <= 1));

    }

    /// <summary>
    /// 检查当前动作进度的一个接口，是否处于动作的前摇/后摇阶段 是否能打断掉
    /// </summary>
    /// <param name="config"></param>
    /// <returns></returns>
    public bool CheckConfig(float config)
    {
        //检查当前动作进度
        if (config == 0) return false;
        return ((animationService.normalizedTime > 0 && animationService.normalizedTime <= config));

    }

    private void OnMove()
    {
        if (UInput.GetAxis_Horizontal() != 0 || UInput.GetAxis_Vertical() != 0)
        {

            if (CheckConfig(currentState.excel_Config.on_move))
            {
                ToNext((int)currentState.excel_Config.on_move[2]);

            }
        } 
    }


    bool ground_check = true;
    public void ToGround()
    {
        if (ground_check)
        {
            //检测 true ->检测到地面 
            if(Physics.Linecast(_transform.position, _transform.position+GameDefine._Ground_dst, GameDefine.Ground_LayerMask))
            {
                ground_check = false; //如果已经在地面 就关掉射线检测 减少性能消耗
            }
            else
            {
                Move(_transform.up * -9.81f, false, false, false, false);
            }

        }
    }
    /// <summary>
    ///  移动核心接口 动作位移配置 输入位移wasd 击飞 击退 --都是走这个接口
    /// </summary>
    /// <param name="dir">方向</param>
    /// <param name="transforDirction">是否将本地坐标转为世界空间坐标 </param>
    /// <param name="delteTime"> 是否乘上delteTime </param>
    /// <param name="_add_gravity"></param>
    /// <param name="_do_ground_check">结束后是否开启地面检测  </param>
    public void Move(Vector3 dir,bool isTransforDirction,bool delteTime = true,bool _add_gravity =true,bool _do_ground_check = true)
    {
        if(isTransforDirction)
        {
            dir = this._transform.TransformDirection(dir);
        }

        Vector3 d2;
        if(_add_gravity)
        {
            d2 = (dir+ GameDefine. _Gravity) *(delteTime? GameTime.deltaTime :1);
        }
        else
        {
            d2 = dir * (delteTime ?GameTime.deltaTime:1);
        }

        characterController.Move(d2);

        if(_do_ground_check)
        {
            ground_check = true; //地面检测
        }


    }

    /// <summary>
    /// 旋转核心接口
    /// </summary>
    public void Rotation(Vector3 inputDir)
    {
        _targetRotation = Mathf.Atan2(inputDir.normalized.x, inputDir.normalized.z) * Mathf.Rad2Deg + GameDefine._Camera.eulerAngles.y;
        float rotation = Mathf.SmoothDampAngle(_transform.eulerAngles.y, _targetRotation, ref _rotationVeloctity, rotationSmoothTime);
        _transform.rotation = Quaternion.Euler(0.0f, rotation, 0.0f);
    }
    public List<FSMServiceiBase>fSMServices = new List<FSMServiceiBase>();
    AnimationService animationService; //动画服务管理
    PhysicsService physicsService; //物理服务管理
    ObjService objectService; //子物体服务管理
    HitlagService hitlagService; //顿帧管理
    RadialBlurService radialBlurService; //径向模糊
    HitService hitService;
    NavigationService navGraphService;


    public T AddService<T>() where T : FSMServiceiBase, new()
    {
        var service = new T();
        fSMServices.Add(service);
        service.Init(this);
        return service;

         // LShinobi_full/root/pelvis/spine_01/spine_02/spine_03/clavicle_r/upperarm_r/lowerarm_r/hand_r/Weapon_r/
    }

    //注册不同的服务组件

    int service_count;
    public void ServiceInit()
    {

        animationService = AddService<AnimationService>();
        physicsService = AddService<PhysicsService>();
        objectService = AddService<ObjService>();
        //if (Ai)
        //{
        //    for (int i = 0; i < fSMServices.Count; i++)
        //    {
        //        Debug.Log($"Service:___{fSMServices[i].GetType()}");
        //    }
        //    Debug.Log("pppppppppppppppppppppppp");
        //    Debug.Log($"{objectService.player.name}");
        //}
            
        hitlagService = AddService<HitlagService>();
        radialBlurService = AddService<RadialBlurService>();
        hitService = AddService<HitService>();
        navGraphService = AddService<NavigationService>();
        service_count = fSMServices.Count;
    }

    public void Attack_Hitlag(PlayerState state)
    {
        hitlagService.DoHitlag_OnAttack(this.animationService.normalizedTime, state);
    }

    public void ServicesOnBegin()
    {
        for(int i = 0; i < service_count; i++)
        {
            fSMServices[i].OnBegin(currentState);
        }
    }
    public bool ServicesOnUpdate()
    {
        int crn_state_id = currentState.id;
        for (int i = 0; i < service_count; i++)
        {
            fSMServices[i].OnUpdate(animationService.normalizedTime,currentState);
            if (crn_state_id != currentState.id)
                return false;
        }
        return true;
    }

    public void ServicesOnEnd()
    {
        for (int i = 0; i < service_count; i++)
        {
            fSMServices[i].OnEnd(currentState);
        }
    }

    public void ServicesOnAnimationEnd()
    {
        for (int i = 0; i < service_count; i++)
        {
            fSMServices[i].OnAnimationEnd(currentState);
        }
    }

    public void ServicesOnRestart()
    {
        for (int i = 0; i < service_count; i++)
        {
            fSMServices[i].ReStart(currentState);
        }
    }

    public void ServicesOnDisable()
    {
        for (int i = 0; i < service_count; i++)
        {
            fSMServices[i].OnDisable(currentState);
        }
    }

    //这里有个细节 传进来的是 是否忽略重力 true 表示的是忽略重力 move接口的是添加重力
    public void AddForce(Vector3 speed, bool ignore_gravity)
    {
        Move(speed, true, _add_gravity: ignore_gravity == false, _do_ground_check: !ignore_gravity);
    }

    public int GetEnemyLayerMask()
    {
        if (Ai)
        {
            return GameDefine.Player_LayerMask;
        }
        else
        {
            return GameDefine.Enemy_LayerMask;
        }
    }

    public void RemoveForce()
    {
        
    }

    Dictionary<string, GameObject> hangPoint = new Dictionary<string, GameObject>();
    public GameObject GetHangPoint(string o_id)
    {
        if(hangPoint.TryGetValue(o_id,out var x))
        {
            return x;
        }

        GameObject obj = _transform.Find(o_id).gameObject;
        if (obj != null)
        {
            hangPoint.Add(o_id, obj);
            return obj;
        }
        else
        {
            hangPoint.Add(o_id, null);
            return null;
        }
    }

   

    internal bool IsBlockState()
    {
        return currentState != null && (currentState.id == 1013 || currentState.id == 10131);
    }

    /// <summary>
    /// 攻击者
    /// </summary>
    /// 
    [HideInInspector]
    public FSM atk_target;
    //0 前方受击 1后方受击
    public void OnHit(int fd,FSM fsm)
    {
        atk_target = fsm;
        if (currentState.excel_Config.on_hit != null)
        {
            //if (fd == 0)
            //{
            //    ToNext(currentState.excel_Config.on_hit[0]);
            //}
            //else if(fd == 1)
            //{
            //    ToNext(currentState.excel_Config.on_hit[1]);
            //}
            ToNext(currentState.excel_Config.on_hit[fd]);
        }
    }

    public void OnDeath(int fd, FSM fsm)
    {
        atk_target = fsm;
        if (currentState.excel_Config.on_hit != null)
        {
            //if (fd == 0)
            //{
            //    ToNext(currentState.excel_Config.on_hit[0]);
            //}
            //else if(fd == 1)
            //{
            //    ToNext(currentState.excel_Config.on_hit[1]);
            //}
            ToNext(currentState.excel_Config.on_death[fd]);
            characterController.enabled = false;

            //击杀boes 特殊逻辑处理


            //主角死亡特殊处理 
        }

    }

    //-----------------------------下面这两个接口以后都是要改成GP接口的 统一处理
    /// <summary>
    /// 格挡成功
    /// </summary>
    public void BlockSucess(FSM atk)
    {
        atk_target = atk;
        if (currentState.excel_Config.on_block_succes != 0)
        {
            ToNext(currentState.excel_Config.on_block_succes);
        }
    }

    /// <summary>
    /// 被振/被闪/被弹
    /// </summary>
    /// <param name="fsm"></param>
    public void BeBlock(FSM fsm)
    {
        atk_target = fsm;
        if (currentState.excel_Config.be_block !=null)
        {

            if (_transform.ForwardOrBack(fsm._transform.position) > 0)
            {
                ToNext(currentState.excel_Config.be_block[0]);
            }
            else
            {
                ToNext(currentState.excel_Config.be_block[1]);
            }
        }

    }

    internal float  GetMoveSpeed()
    {
        return moveSpeed * 1.5f;
    }

    Vector3 bash_add_fly;
    Vector3 bash_fly_dir;
    internal void OnBash(int fd, FSM player, float[] add_fly, Vector3 point)
    {
        atk_target = player;
        bash_add_fly = new Vector3(add_fly[0], add_fly[1], add_fly[2]);
        bash_fly_dir = this._transform.position - player.transform.position;

        if (currentState.excel_Config.on_bash != null)
        {
            ToNext(currentState.excel_Config.on_bash[fd]);
        }
    }

    public void OnBashUpdate()
    {
        // 时长 0.2 0.1上升 0.1下降
        var f = GameTime.time - currentState.begin;
        if(f < 0.1f)
        {
            var d = bash_fly_dir * (bash_add_fly[2] / 0.2f);            
            d.y = bash_add_fly.y/0.2f;
            Move(d, false,_add_gravity:false,_do_ground_check:false);
        }
        else if (f <=0.2f)
        {
            var d = bash_fly_dir * (bash_add_fly[2] / 0.2f);
            d.y =-(bash_add_fly.y / 0.2f *2);
            Move(d, false, _add_gravity: false, _do_ground_check: false);
        }


    }

    public void OnBashEnd()
    {
        ground_check = true;
    }
}


public class PlayerState
{
    public int id;
    public PlayerStateEntity excel_Config;

    //动作通知事件
    public StateEntity stateEntity;
    public float clipLength;
    public SkillEntity skill;
    public float begin;//进入状态的开始时间

    public void SetBeginTime()
    {
        begin = GameTime.time;
    }


    public bool IsCD()
    {
        if(skill!= null)
        {
            return false;
        }
        return GameTime.time - begin <= skill.cd;
    }

    public string Info()
    {
        return $"状态:{id}_{excel_Config.info}";
    }

}

public enum StateEventType
{
    begin,//开始进入
    update, //状态每帧更新
    end, //状态结束
    animtionEnd, //动作结束

}



